#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "rwlock_pthread.h"

void rwlock_init(rwlock_t *lock) {
    pthread_mutex_init(&lock->mutex, NULL);
    pthread_cond_init(&lock->read_cond, NULL);
    pthread_cond_init(&lock->write_cond, NULL);
    lock->reader_count = 0;
    lock->writer_count = 0;
    lock->owner_thread = pthread_self();
    lock->lock_count = 0;
    lock->initialized = 1;
}

void rwlock_lock_read(rwlock_t *lock) {
    pthread_mutex_lock(&lock->mutex);

    // 检查当前线程是否已经持有写锁
    if (pthread_equal(lock->owner_thread, pthread_self())) {
        lock->lock_count++;
        pthread_mutex_unlock(&lock->mutex);
        return;
    }

    // 等待直到没有写者
    while (lock->writer_count > 0) {
        pthread_cond_wait(&lock->read_cond, &lock->mutex);
    }

    // 增加读者计数
    lock->reader_count++;
    pthread_mutex_unlock(&lock->mutex);
}

void rwlock_unlock_read(rwlock_t *lock) {
    pthread_mutex_lock(&lock->mutex);

    // 检查当前线程是否持有写锁
    if (pthread_equal(lock->owner_thread, pthread_self())) {
        if (--lock->lock_count == 0) {
            lock->owner_thread = (pthread_t)0; // 重置写锁拥有者
        }
    } else {
        // 减少读者计数
        if (--lock->reader_count == 0) {
            pthread_cond_signal(&lock->write_cond); // 唤醒等待写锁的线程
        }
    }

    pthread_mutex_unlock(&lock->mutex);
}

void rwlock_lock_write(rwlock_t *lock) {
    pthread_mutex_lock(&lock->mutex);

    // 检查当前线程是否已经持有写锁
    if (pthread_equal(lock->owner_thread, pthread_self())) {
        lock->lock_count++;
        pthread_mutex_unlock(&lock->mutex);
        return;
    }

    // 等待直到没有读者和写者
    while (lock->reader_count > 0 || lock->writer_count > 0) {
        pthread_cond_wait(&lock->write_cond, &lock->mutex);
    }

    // 获取写锁
    lock->owner_thread = pthread_self();
    lock->lock_count = 1;
    lock->writer_count++;
    pthread_mutex_unlock(&lock->mutex);
}

void rwlock_unlock_write(rwlock_t *lock) {
    pthread_mutex_lock(&lock->mutex);

    if (!pthread_equal(lock->owner_thread, pthread_self())) {
        fprintf(stderr, "Unlocking a write lock that is not owned by this thread\n");
        pthread_mutex_unlock(&lock->mutex);
        exit(EXIT_FAILURE);
    }

    if (--lock->lock_count == 0) {
        lock->owner_thread = (pthread_t)0; // 重置写锁拥有者
        lock->writer_count--;
        pthread_cond_broadcast(&lock->read_cond); // 唤醒所有等待读锁的线程
        pthread_cond_signal(&lock->write_cond); // 唤醒等待写锁的线程
    }

    pthread_mutex_unlock(&lock->mutex);
}

void rwlock_destroy(rwlock_t *lock) {
    pthread_mutex_destroy(&lock->mutex);
    pthread_cond_destroy(&lock->read_cond);
    pthread_cond_destroy(&lock->write_cond);
    lock->destroyed = 1;
}